package spark

import (
	"errors"
	"fmt"
	"time"

	"github.com/gorilla/websocket"
	"github.com/swxctx/xlog"
)

// ChatRequest 调用请求结构体
type ChatRequest struct {
	// 每个用户的id，用于区分不同用户[最大长度32]
	Uid string
	// 消息信息
	Messages []MessageInfo
	// 其他参数信息
	ChatParameter RequestParameterChat
}

type Client struct {
	// 基础请求api
	baseUri string

	// appId 应用appid
	appId string
	// apiKey APIKey
	apiKey string
	// apiSecret APISecret
	apiSecret string

	// 是否调试模式[调试模式可以输出详细的信息]
	debug bool

	// 用于请求
	webSocketDialer *websocket.Dialer
}

func NewClient(appId, apiKey, apiSecret string, debug ...bool)(*Client){
	client := &Client{
		appId:     appId,
		apiKey:    apiKey,
		apiSecret: apiSecret,
		baseUri:   "wss://spark-api.xf-yun.com/%s/chat",
	}
	if len(debug) > 0 {
		client.debug = debug[0]
		xlog.SetLevel("debug")
	}

	// websocket
	client.webSocketDialer = &websocket.Dialer{
		HandshakeTimeout: 5 * time.Second,
	}

	return client
}

func MustNewClient(appId, apiKey, apiSecret string, debug ...bool)(*Client){
	cli := NewClient(appId,apiKey,apiSecret,debug...)
	return cli
}

// SetDebug debug开关
func (client *Client)SetDebug(debug bool) {
	client.debug = debug
}

func (client *Client)GetAppId()string{
	return client.appId
}

func (client *Client)GetApiKey()string{
	return client.apiKey
}

func (client *Client)GetApiSecret()string{
	return client.apiSecret
}


// ChatStream 讯飞对话接口
func (c *Client) ChatStream(chatRequest *ChatRequest) (*StreamReader, error) {
	// 处理请求域
	requestUrl := fmt.Sprintf(c.baseUri, model_api_map[chatRequest.ChatParameter.Domain])

	// 处理请求参数
	requestParams := &xfRequest{
		Header: requestHeader{
			AppId: c.appId,
			Uid:   chatRequest.Uid,
		},
		Parameter: requestParameter{
			Chat: chatRequest.ChatParameter,
		},
		Payload: requestPayload{
			Message: requestPayloadMessage{
				Text: chatRequest.Messages,
			},
		},
	}

	// 处理请求链接
	finalUrl := assembleAuthUrl1(requestUrl, c.apiKey, c.apiSecret)

	if c.debug {
		xlog.Debugf("xunfei: Chat request url-> %s", finalUrl)
	}

	// 发起连接
	conn, resp, err := c.webSocketDialer.Dial(finalUrl, nil)
	if err != nil {
		return nil, fmt.Errorf("xunfei: Chat connect err-> %v", err)
	} else if resp.StatusCode != 101 {
		return nil, fmt.Errorf("xunfei: Chat connect status invalid, code-> %d", resp.StatusCode)
	}

	// 发送数据
	if err := conn.WriteJSON(requestParams); err != nil {
		return nil, fmt.Errorf("xunfei: Chat WriteJSON err-> %v", err)
	}

	return newStreamReader(conn), nil
}

func (c *Client)CreateChatStream(model,content string,temperature float64,maxTokens int)(*StreamReader,error){
	if model_api_map[model] == ""{
		return nil,errors.New("未知模型名称")
	}
	sr,err := c.ChatStream(&ChatRequest{
		Messages: []MessageInfo{
			{
				Role:    CHAT_MESSAGE_ROLE_USER,
				Content: content,
			},
		},
		ChatParameter: RequestParameterChat{
			Domain: model,
			Temperature: temperature,
			MaxTokens: maxTokens,
		},
	})
	if err != nil {
		return nil,errors.New(err.Error())
	}
	return sr,nil
}